package com.tomtop.core.utils;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
 * 
 * @author lenovo
 * 方法介绍
 * 	n 		: 创建
 * 	a 		: 添加
 *  cv  	: 判断是否存在
 *  r  		: 删除
 *  c  		: 清理
 *  s  		: 大小
 *  g		: 取出
 *  to  	: 转化为原型
 *  each  	: 遍历
 *  filter  : 过滤
 *  group  	: 分组
 *  join	: 数组拼装为字符串，调用toString
 *  list	: 重写list的值，保持原有序列的顺序
 *  sort	: 排序
 * @param <T>
 */

public final class ListUtils<T> {

	@FunctionalInterface public static interface GroupIterable<V, K> { K accept(V v); }
	@FunctionalInterface public static interface EachIterable<T> { void accept(T t); }
	@FunctionalInterface public static interface FilterIterable<T> { boolean test(T t); }
	@FunctionalInterface public static interface ListNewList<T,N> { N accept(T t); }
	@FunctionalInterface public static interface MaxOrMin<T,N extends Comparable<N>> { N accept(T t); }
	@FunctionalInterface public static interface OrderBy<T,N extends Comparable<N>> { N accept(T t); }
	
	private List<T> list=new LinkedList<>();
	private ListUtils() {
	}
	public static <T> ListUtils<T> n(Collection<T> collection) {
		return new ListUtils<T>().a(collection);
	}
	public static <T> ListUtils<T> n() {
		return n(null);
	}
	public ListUtils<T> a(T t) {
		if(t!=null)
			this.list.add(t);
		return this;
	}
	public ListUtils<T> a(@SuppressWarnings("unchecked") T ... ts) {
		for (T t : ts) {
			this.list.add(t);
		}
		return this;
	}
	public ListUtils<T> a(Collection<T> ts) {
		if(ts!=null)
			this.list.addAll(ts);
		return this;
	}
	public boolean cv(T t) {
		return this.list.contains(t);
	}
	public int s() {
		return this.list.size();
	}
	public T g(int index) {
		return this.list.get(index);
	}
	public ListUtils<T> r(int ... indexs) {
		for (int index : indexs) {
			this.list.remove(index);
		}
		return this;
	}
	public ListUtils<T> r( T t) {
		this.list.remove(t);
		return this;
	}
	public ListUtils<T> r(@SuppressWarnings("unchecked") T ... ts) {
		for (T t : ts) {
			this.list.remove(t);
		}
		return this;
	}
	public ListUtils<T> c() {
		this.list.clear();
		return this;
	}
	public List<T> to() {
		return this.list;
	}
	
	public ListUtils<T> each(EachIterable<? super T> eachIterable) {
		Iterator<T> it = this.list.iterator();
		while (it.hasNext()) {
			T t = (T) it.next();
			eachIterable.accept(t);
		}
		return this;
	}

	public <N extends Comparable<N>> ListUtils<T> order(OrderBy<T,N> orderby) {
		this.list.sort((t1,t2)->orderby.accept(t1).compareTo(orderby.accept(t2)));
		return this;
	}

	public <N extends Comparable<N>> ListUtils<T> orderDesc(OrderBy<T,N> orderby) {
		this.list.sort((t1,t2)->-1*orderby.accept(t1).compareTo(orderby.accept(t2)));
		return this;
	}
	
	public <N extends Comparable<N>> T min(MaxOrMin<? super T,N> maxOrMin) {
		return m(maxOrMin, -1);
	}
	
	public <N extends Comparable<N>> T max(MaxOrMin<? super T,N> maxOrMin) {
		return m(maxOrMin, 1);
	}
	
	private <N extends Comparable<N>> T m(MaxOrMin<? super T,N> maxOrMin,int status) {
		if(isEmpty(this.list))
			return null;
		T mcv=null;
		N mom=null;
		for (T t : list) {
			N cv = maxOrMin.accept(t);
			if(cv==null) 
				continue;
			if(mcv==null){
				mcv=t;
				mom=cv;
				continue;
			}
			if(cv.compareTo(mom)*status>0){
				mcv=t;
				mom=cv;
			}
		}
		return mcv;
	}
	
	public ListUtils<T> filter(FilterIterable<? super T> filter) {
		this.list.removeIf(t->!filter.test(t));
		return this;
	}
	
	public <N> ListUtils<N> list(ListNewList<? super T,N> lnl) {
		ListUtils<N> lu=ListUtils.n();
		this.each(t->{
			N n=lnl.accept(t);
			if(n!=null)
				lu.a(n);
		});
		return lu;
	}
	
	public <K> MapUtils<K,List<T>> group(GroupIterable<? super T, K> groupIterable) {
		MapUtils<K,List<T>> relust=MapUtils.n(); 
		this.each(t->{
			if(t==null)
				return;
			K key= groupIterable.accept(t);
			if(key==null)
				return;
			List<T> it=relust.ck(key)?relust.g(key):new LinkedList<>();
			it.add(t);
			relust.a(key, it);
		});
		return relust;
	}
	
	public String join(){
		return this.join(null);
	}
	
	public String join(String seg) {
		if(list.size()==0)return "";
		if(seg==null)
			seg="";
		StringBuffer ret= new StringBuffer(list.get(0)+"");
		for (T t : list) {
			ret.append(seg);
			ret.append(t);
		}
		return ret.toString();
	}
	
	public static boolean isNotEmpty(Collection<?> ... collections) {
		for (Collection<?> collection : collections) {
			if(collection==null||collection.isEmpty())
				return false;
		}
		return true;
	}
	
	public static boolean isEmpty(Collection<?> ...args) {
		return !isNotEmpty(args);
	}
}
